package com.mattc.autotyper.gui.fx;
import javafx.event.ActionEvent;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextInputControl;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
import javafx.util.Duration;
import com.mattc.autotyper.util.Console;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class FXGuiUtils {
public static void setTooltipDelay(Tooltip tooltip, double openDelayInMillis, double closeDelayInMillis, double visibleDurationInMillis) {
try {
Class<?> TTBehaviourClass = null;
Class<?>[] declaredClasses = Tooltip.class.getDeclaredClasses();
for (Class c : declaredClasses) {
if (c.getCanonicalName().equals("javafx.scene.control.Tooltip.TooltipBehavior")) {
TTBehaviourClass = c;
break;
}
}
if (TTBehaviourClass == null) {
// abort
return;
}
Constructor<?> constructor = TTBehaviourClass.getDeclaredConstructor(
Duration.class, Duration.class, Duration.class, boolean.class);
if (constructor == null) {
// abort
return;
}
constructor.setAccessible(true);
Object newTTBehaviour = constructor.newInstance(
new Duration(openDelayInMillis), new Duration(visibleDurationInMillis),
new Duration(closeDelayInMillis), false);
Field ttbehaviourField = Tooltip.class.getDeclaredField("BEHAVIOR");
if (ttbehaviourField == null) {
// abort
return;
}
ttbehaviourField.setAccessible(true);
// Cache the default behavior if needed.
Object defaultTTBehavior = ttbehaviourField.get(Tooltip.class);
ttbehaviourField.set(Tooltip.class, newTTBehaviour);
} catch (Exception e) {
Console.exception(e);
}
}
public static void setToggleTextSwitch(final ToggleButton btn, final String onText, final String offText) {
btn.addEventHandler(ActionEvent.ACTION, (event) -> {
if (btn.isSelected()) {
btn.setText(onText);
} else {
btn.setText(offText);
}
});
btn.fireEvent(new ActionEvent());
}
public static void setMaxCharCount(final TextInputControl control, final int count) {
control.addEventFilter(KeyEvent.KEY_TYPED, (event) -> {
final String text = control.getText();
if (text.length() == count) {
event.consume();
} else if (text.length() > count) {
control.setText(text.substring(0, count));
event.consume();
}
});
}
public static boolean addTogglesToGroup(ToggleGroup group, Toggle... toggles) {
return group.getToggles().addAll(toggles);
}
public static boolean addTogglesToGroup(MetaToggleGroup group, Toggle... toggles) {
for (final Toggle t : toggles) {
group.add(t, "");
}
return true;
}
public static Point2D getScreenCoordinates(Node node) {
final double x = node.getScene().getWindow().getX();
final double y = node.getScene().getWindow().getY();
final Bounds localBounds = node.localToScene(node.getBoundsInLocal());
return new Point2D(x + localBounds.getMinX(), y + localBounds.getMaxY());
}
public static boolean canUseJavaFX() {
try {
return Class.forName("javafx.application.Application") != null;
} catch (final ClassNotFoundException e) {
return false;
}
}
/**
* Please use {@link Stage#setAlwaysOnTop(boolean)} instead.
*/
@Deprecated
public static void makeAlwaysOnTop(final Stage stage) {
stage.setAlwaysOnTop(true);
}
public static Alert buildLongAlert(String context, String longMessage, Node... additional) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText(context);
Label label = new Label("Details: ");
TextArea textArea = new TextArea(longMessage);
textArea.setEditable(false);
textArea.setWrapText(false);
textArea.setMaxHeight(Double.MAX_VALUE);
textArea.setMaxWidth(Double.MAX_VALUE);
GridPane.setVgrow(textArea, Priority.ALWAYS);
GridPane.setHgrow(textArea, Priority.ALWAYS);
GridPane expanded = new GridPane();
expanded.setMaxWidth(Double.MAX_VALUE);
expanded.add(label, 0, 0);
expanded.add(textArea, 0, 1);
for (int i = 0; i < additional.length; i++)
expanded.add(additional[i], 0, 2 + i);
alert.getDialogPane().setContent(expanded);
alert.getDialogPane().setPrefWidth(700);
alert.getDialogPane().setPrefHeight(400);
return alert;
}
public static Alert buildException(Exception e) {
return buildException(e.getClass().getSimpleName() + " : " + e.getMessage(), e);
}
public static Alert buildException(String context, Exception e) {
Alert alert = new Alert(Alert.AlertType.ERROR, context);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
String text = sw.toString();
Label label = new Label("Exception Stack Trace: ");
TextArea textArea = new TextArea(text);
textArea.setEditable(false);
textArea.setWrapText(false);
textArea.setMaxHeight(Double.MAX_VALUE);
textArea.setMaxWidth(Double.MAX_VALUE);
GridPane.setVgrow(textArea, Priority.ALWAYS);
GridPane.setHgrow(textArea, Priority.ALWAYS);
GridPane expanded = new GridPane();
expanded.setMaxWidth(Double.MAX_VALUE);
expanded.add(label, 0, 0);
expanded.add(textArea, 0, 1);
alert.getDialogPane().setContent(expanded);
alert.getDialogPane().setPrefWidth(800);
alert.getDialogPane().setPrefHeight(600);
return alert;
}
}